package multidraw.model;

import java.awt.Color;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;

import multidraw.tools.SelectorTool;
import multidraw.tools.Tool;

/**
 * This class serves as the local cache of the remote model. It helps 
 * accelerating the communication between the central server and the clients.
 * Reduce network traffic.
 * @author Cuong Bui.
 * @version 1.0.
 */
public class CanvasServer implements CanvasModel {
	List<Shape> data = new ArrayList<Shape>();
	List<CentralCanvasObserver> observers = new ArrayList<CentralCanvasObserver>();
	List<String> userList = new ArrayList<String>();
	List<String> activeUserList = new ArrayList<String>();
	
	private Tool currentTool;
	private Color penColor = Color.black;
	
	//Shape selectedObject = null;
	int selectedObjectIndex = -1;
	
	public CanvasServer() {
		
	}
	
	public Shape getSelectedObject() {
		if (selectedObjectIndex >= 0 && selectedObjectIndex < data.size())
			return data.get(selectedObjectIndex);
		else return null;
	}
	
	public int getSelectedObjectIndex() {
		return selectedObjectIndex;
	}

	public int attachObserver(CentralCanvasObserver o) {
		observers.add(o);
		
		return 0;
	}
	
	public void notifyObservers() {
		for (CentralCanvasObserver o: observers) {
			try {
				o.updateModelContent();
			} catch (RemoteException e) {
				System.err.println(e);
			}
		}
	}
	
	public List<Shape> getData() {
		return data;
	}
	
	public void addShape(Shape s) {
		data.add(s);
		notifyObservers();
	}
	
	public void selectObject(int X, int Y) {
		for (int i = data.size() - 1; i >= 0; i--) {
			Shape s = data.get(i);
			
			if (s.isInsideSelectionalArea(X, Y)) {
				//selectedObject = s;
				selectedObjectIndex = i;
				//JOptionPane.showMessageDialog(null, "Selected");
				notifyObservers();
				return;
			}
		}
		
		selectedObjectIndex = -1; //no object selected
		//JOptionPane.showMessageDialog(null, "None Selected");
		notifyObservers();
	}
	
	public void setCurrentTool(Tool t) {
		currentTool = t;
		if (!(currentTool instanceof SelectorTool)) {
			selectedObjectIndex = -1; //deselect all objects.
		}
		notifyObservers();
	}
	
	public Tool getCurrentTool() {
		return currentTool;
	}
	
	public void clearCanvas() {
		data.clear();
		//fixed the null pointer exception in getSelectedObject.
		selectedObjectIndex = -1;
		//update all View
		notifyObservers();
	}
	//public void fillShape
	public Color getPenColor() {
		return penColor;
	}
	
	public void setPenColor(Color c) {
		System.out.println("Canvas color change ...");
		System.out.println("color = " + c);
		penColor = c;
		notifyObservers();
	}
	
	public void deleteSelectedObject() {
		if (selectedObjectIndex >= 0) {
			data.remove(selectedObjectIndex);
			selectedObjectIndex = -1;
		}
		notifyObservers();
	}
	
	/**
	 * Switch filling option of currently selected object
	 */
	public void switchSelectedObjectFilling(){
		if (getSelectedObject() != null) {
		    getSelectedObject().switchFilling();
		    notifyObservers();
		}
	}
	
	public static void main(String[] args) {
		try {
			CanvasServer obj = new CanvasServer();
			CanvasModel stub = (CanvasModel) UnicastRemoteObject.exportObject(obj, 0);
			
			//Bind the remote object's stub in the registry
			Registry registry = LocateRegistry.getRegistry();
			registry.bind("CanvasModel", stub);
			
			System.err.println("Server ready");			
		} catch (Exception e) {
			System.err.println("Server exception: " + e.toString());
			e.printStackTrace();
		}
	}

	@Override
	public void detachObserver(CentralCanvasObserver o) throws RemoteException {
		// TODO Auto-generated method stub
		
	}
}
